

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <glib.h>
#include <glib/gprintf.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <math.h>



#include <sys/types.h>
#include <sys/socket.h>
#include<sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/if.h>
#include <ifaddrs.h>


#include "gps_functions.h"
#include "globals.h"
#include "support.h"
#include "tile_management.h"
#include "map_management.h"
#include "converter.h"
#include "wp.h"
#include "tracks.h"
#include "livetracks.h"
#include "hrm_functions.h"

#define BUFSIZE 512
char * distance2scale(float distance, float *factor);
void * get_gps_thread(void *ptr);


static GIOChannel *gpsd_io_channel =NULL;

static guint sid1,  sid3; 
guint watchdog;

//获取无线网卡的IP
struct in_addr get_wireless_ip(char* wlanx){
	struct ifreq ifreq;

    int sockfd=socket(AF_INET,SOCK_DGRAM,0);
	/* Enable address reuse */
	 int on = 1;
	 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
    if(sockfd<0)
        printf("get_wireless_ip create socket error\n");

    strcpy(ifreq.ifr_ifrn.ifrn_name,wlanx);

    if(ioctl(sockfd,SIOCGIFADDR,&ifreq)<0)     //提取地址信息
    	printf("get_wireless_ip ioctl error,IP Address.\n");

    close(sockfd);
	return ((struct sockaddr_in*)&(ifreq.ifr_addr))->sin_addr;
}



//接收广播的节点信息，然后进行处理。
void *
socket_recv(void *ptr)
{



	GdkGC *gc_point;
	int pixel_x, pixel_y, x, y;
//
//					//gc_point = map_drawable->style->fg_gc[GTK_WIDGET_STATE (map_drawable)];
	//gc_point = gdk_gc_new(pixmap);

    struct sockaddr_in s_addr;
    struct sockaddr_in c_addr;
    socklen_t addr_len;
	float lat, lon;
	char test_buf[50];
	int sock;
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
        perror("socket()");
    }

    int yes = 1;
    setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));

    /* Enable address reuse */
	int on = 1;
	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );

    memset(&s_addr, 0, sizeof(struct sockaddr_in));

    /* 设置地址和端口信息 */
    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(Server_Port_node_information);
    s_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    /* 绑定地址和端口信息 */
    if ((bind(sock, (struct sockaddr *) &s_addr, sizeof(s_addr))) == -1)
    {
        perror("bind()");
        //exit(errno);
    }else{
    	printf("bind success! \n");
    }

    /* 循环接收数据 */
    addr_len = sizeof(c_addr);

    gc_point = gdk_gc_new(pixmap);

    while (1)
    {
    	printf("waiting for ngb node information... \n");
    	recvfrom(sock, test_buf, sizeof(test_buf) - 1, 0, (struct sockaddr *) &c_addr, &addr_len);
    	printf("Recv From%s:%d Message:%s\n",inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port), test_buf);

        //处理接收到的数据
//        char *outer_ptr=NULL;
//        char *inner_ptr=NULL;
        int in=0;
        char tp[3][50];
        char *node_name_tmp;
//        char *buf=test_buf;

//        //碰到 | 符号，进行分割
//        while((p[in]=strtok_r(buf,"|",&outer_ptr))!=NULL) {
//            buf=p[in];
//            while((p[in]=strtok_r(buf," ",&inner_ptr))!=NULL) {
//                  in++;
//                  buf=NULL;
//             }
//            //p[in++]="***";
//            buf=NULL;
//        }
//        //处理完毕

       // printf("recv-p[0]:lat %f,\t lon %f \n",p[0],p[1]);

        //从p[0]中获取IP 192.168.3.2 的最后一个数字
       //int node_index=(atoi(rindex(p[0],'.')+1)-1);

    	//使用g_strsplit
    	gchar **t, **p;
    	t = g_strsplit(test_buf,"|",3);
    	for (p = t; *p; p++){
    		printf("%s\n", *p);
    		sprintf(tp[in],"%s",*p);
    		in++;

    	}
    	//sprintf(tp[0],"%s",*p);
    	//p++;
    	//sprintf(tp[1],"%s",*p);
    	//lat=(float)*p;
    	//p++;
    	//lon=(float)*p;

    	  g_strfreev(t);


	   //赋值
    	// sprintf(ip_tmp,"%s",tp[0]);
    	  node_name_tmp=tp[0];

    	  //获取本地网卡IP
    	  	//char *wlanX_ip_tmp=(char *)inet_ntoa(get_wireless_ip(WLANX));

    	 printf("socket recv:  node_name_tmp:%s\n",node_name_tmp);
         //如果节点是本地IP，跳过
        if(!strcmp(Node_3_Name,node_name_tmp)){
         	printf("相同...\n");
        	continue;
         }else{
        	 printf("是邻居发过来的。\n");
         }

       //sprintf(lat,"%f",tp[0]);
       lat=atof(tp[1]);
      // sprintf(lon,"%s",tp[1]);
       lon=atof(tp[2]);
       printf("socket recv:  recv:lat %f,\t lon %f \n",lat,lon);

       //绘图队列
       //gtk_widget_queue_draw(map_drawable);

       //进入线程，对gtk界面进行操作
       gdk_threads_enter();



       //绘画
		pixel_x = lon2pixel(global_zoom, lon);
		pixel_y = lat2pixel(global_zoom, lat);
		printf("socket recv:  pixel_x的X轴：%d\tY轴：%d\n",pixel_x,pixel_y);

		x = pixel_x - global_x;
		y = pixel_y - global_y;
		printf("  global_x的X轴：%d\tY轴：%d\n",global_x,global_y);
		printf("socket recv:  x：%d\tY：%d\n",x,y);

		//半径为30
		//gdk_draw_arc (pixmap,gc_point,TRUE,x, y,30,30,0,234320);

		//画上朋友，小人图标
		gdk_draw_pixbuf(map_drawable->window, gc_point,
					gdk_pixbuf_new_from_file("./tangogps-friend.png", NULL),
					0, 0, x, y, -1, -1,
					GDK_RGB_DITHER_NORMAL, 0, 0);
		printf("socket recv:画完了这点\n\n");


		//写文字
		PangoLayout *layout;
		//gchar *s_utf8=node.nodeinfo;
		gchar *s_utf8=node_name_tmp;
		layout = pango_layout_new(gdk_pango_context_get());
		pango_layout_set_text(layout, s_utf8, -1);
		//gdk_draw_layout(drawable, gc, (node.x-20), (node.y+25), layout);
		gdk_draw_layout(map_drawable->window, gc_point, x+50, y, layout);


		//释放内存
		g_object_unref(layout);
		//g_object_unref (gc_point);

		//更新gdk
		//gdk_window_process_all_updates();

		//用完后使用gdk_threads_leave()进行释放
		gdk_threads_leave();
    }

}

//检查邻居的GPS信息
gboolean
check_neighbour_gps_timer()
{
		float lat, lon;

		//如果gpsdata为空，或者能连接上GPSD服务器
		if(!gpsdata  || global_reconnect_gpsd)
			get_gps();//获取GPS信息


		if(gpsdata)
		{
			printf("if you have a gps model...\n");
			//trackpoint_t *tp = g_new0(trackpoint_t,1);

			lat = deg2rad(gpsdata->fix.latitude);
			lon = deg2rad(gpsdata->fix.longitude);
			printf("lat:%f \t  lon:%f \n",lat,lon);
		}
		return TRUE;
}

gboolean	socket_send(char to_send_string[50]){

	struct sockaddr_in s_addr;
	int sock,addr_len;
    /* 创建 socket */
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
        perror("socket()");
        //exit(errno);
    }else{
    	printf("create socket successful ! \n");
    }

	/* Enable address reuse
	 *  端口地址重用
	 */
	int on = 1;
	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );

    /* 设置通讯方式对广播，即本程序发送的一个消息，网络上所有主机均可以收到 */
	int yes = 1;
    setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));


    /* 设置对方地址和端口信息 */
    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(Server_Port_node_information);
    s_addr.sin_addr.s_addr = inet_addr(Broadcast_address);

    /* 发送UDP消息 */
   	addr_len = sizeof(s_addr);

   	//发送信息
   	sendto(sock, to_send_string, strlen(to_send_string), 0, (struct sockaddr *) &s_addr, addr_len);
   	printf("send gps lat,lon finished. \n");
   	memset(to_send_string,0,50);//清空

   	//这里可以判断是否发送成功
   	return TRUE;
}

//gps绘画,节点
gboolean
cb_gps_timer()
{
	gtk_widget_queue_draw(map_drawable);
	
	int pixel_x, pixel_y, x, y, last_x, last_y;
	static float lat, lon, lat_tmp=0, lon_tmp=0;
	float trip_delta=0;

	static double trip_time_accumulated = 0;
	static gboolean trip_counter_got_stopped = FALSE;

	GdkColor color;
	static GdkGC *gc=NULL, *gc_2=NULL, *gc_3=NULL, *gc_4=NULL, *gc_5=NULL;
	
	//获取本地网卡IP
	//char *wlanX_ip=(char *)inet_ntoa(get_wireless_ip(WLANX));		//不需要了。

	//设置gc，GdkGC
	if(gc == NULL)
	{
		gc   = gdk_gc_new(pixmap);
		gc_2 = gdk_gc_new(pixmap);
		gc_3 = gdk_gc_new(pixmap);
		gc_4 = gdk_gc_new(pixmap);
		gc_5 = gdk_gc_new(pixmap);
		
		
		//行车轨迹，是红色
//		color.red = 60000;
//		color.green = 0;
//		color.blue = 0;
		color.red = 0;
		color.green = 60000;
		color.blue = 0;
		gdk_gc_set_rgb_fg_color(gc, &color);
		gdk_gc_set_line_attributes(gc,
				5, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
		
		//环形，原来的是蓝色
//		color.red = 5000;
//		color.green = 5000;
//		color.blue = 55000;
		color.red = 55000;
		color.green = 5000;
		color.blue = 5000;
		gdk_gc_set_rgb_fg_color(gc_2, &color);
		gdk_gc_set_line_attributes(gc_2,
				6, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
	
		
		color.red = 25500;
		color.green = 35000;
		color.blue = 65500;
		gdk_gc_set_rgb_fg_color(gc_3, &color);
		gdk_gc_set_line_attributes(gc_3,
				7, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
		
		
		color.red = 35500;
		color.green = 5000;
		color.blue = 500;
		gdk_gc_set_rgb_fg_color(gc_4, &color);
		gdk_gc_set_line_attributes(gc_4,
				7, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
				
		
		color.red = 65500;
		color.green = 65500;
		color.blue = 65500;
		gdk_gc_set_rgb_fg_color(gc_5, &color);
		gdk_gc_set_line_attributes(gc_5,
				11, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
				
	}
	
//////////////////////////////////////////////
	//自定义座标
//	lat=39.926914;
//			lon=116.192307;
//			GdkColor color_point;
//					GdkGC *gc_point;
//
//					//gc_point = map_drawable->style->fg_gc[GTK_WIDGET_STATE (map_drawable)];
//					gc_point = gdk_gc_new(pixmap);
//					color_point.green = 20000;
//					color_point.blue = 20000;
//					color_point.red = 65000;
//					gdk_gc_set_rgb_fg_color(gc_point, &color_point);
//					gdk_gc_set_line_attributes(
//							gc_point, 5, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
//
//			pixel_x = lon2pixel(global_zoom, lon);
//			pixel_y = lat2pixel(global_zoom, lat);
//
//			x = pixel_x - global_x;
//			y = pixel_y - global_y;
//			printf("x：%d\tY：%d\n",x,y);
//
//
//			pixel_x = lon2pixel(global_zoom, lon_tmp);
//			pixel_y = lat2pixel(global_zoom, lat_tmp);
//			printf("pixel_x的X轴：%d\tY轴：%d\n",pixel_x,pixel_y);
//
//			last_x = pixel_x - global_x;
//			last_y = pixel_y - global_y;
//			printf("last的X轴：%d\tY轴：%d\n",last_x,last_y);
//
//
//			printf("gdk_draw_drawable \n");
//
//			gdk_draw_arc (
//					pixmap,
//				gc_point,
//				TRUE,
//				pixel_x, pixel_y,
//				50,60,
//				0,23040);

//			gdk_draw_drawable (
//				map_drawable->window,
//				map_drawable->style->fg_gc[GTK_WIDGET_STATE (map_drawable)],
//				pixmap,
//				last_x-29, last_y-29,
//				last_x-29 + mouse_dx, last_y-29 + mouse_dy,
//				58,58);

//////////////////////////////////////////////


	//如果gpsdata为空，或者能连接上GPSD服务器
	if(!gpsdata  || global_reconnect_gpsd)
		get_gps();//获取GPS信息
	
	//如果GPS数据为真
	if(gpsdata)
	{
		printf("if you have a gps model...\n");
		trackpoint_t *tp = g_new0(trackpoint_t,1);
		
		//获取GPSD数据
		lat = deg2rad(gpsdata->fix.latitude);
		lon = deg2rad(gpsdata->fix.longitude);
		//lat = (float)0.696807;
		//lon = (float)2.027877;
		//sprintf(lat,"%f",0.696700);
		//sprintf(lon,"%f",2.027800);
		printf("lat:%f \t  lon:%f \n",lat,lon);
		//把经纬度打印到字符串里面。
		char lat_lon_string[50];
		sprintf(lat_lon_string,"%s|%f|%f",Node_3_Name,lat,lon);
		//sprintf(lat_lon_string,"%s|%s","fslkdfjl","64s54f5d");	//for test
		printf("lat_lon_string:%s \n",lat_lon_string);

		//自定义座标
		//lat=39.926914;
		//lon=116.192307;
		
		
		pixel_x = lon2pixel(global_zoom, lon);
		pixel_y = lat2pixel(global_zoom, lat);
		printf("pixel_x的X轴：%d\tY轴：%d\n",pixel_x,pixel_y);
		
		x = pixel_x - global_x;
		y = pixel_y - global_y;
		printf("  global_x的X轴：%d\tY轴：%d\n",global_x,global_y);
		printf("x：%d\tY：%d\n",x,y);
		
		pixel_x = lon2pixel(global_zoom, lon_tmp);
		pixel_y = lat2pixel(global_zoom, lat_tmp);
		printf("pixel_x的X轴：%d\tY轴：%d\n",pixel_x,pixel_y);
		
		last_x = pixel_x - global_x;
		last_y = pixel_y - global_y;
		printf("last的X轴：%d\tY轴：%d\n",last_x,last_y);


		//如果gps数据可以使用
		if(gpsdata->seen_vaild)
		{

			//广播发送字符串
			socket_send(lat_lon_string);
			printf("send lat_lon_string successfule.\n ");

			int hand_x, hand_y, hand_wp_x, hand_wp_y;
			double heading_rad, bearing;
			
			heading_rad = (gpsdata->fix.heading * (1.0 / 180.0)) * M_PI;

			if(gpsdata->fix.speed>0.3) 
			{
				hand_x =  25 * sinf(heading_rad);
				hand_y = -25 * cosf(heading_rad);
			}
			else
			{
				hand_x = 0;
				hand_y = 0;
			}


			//恢复，应该是重绘
			gdk_draw_drawable (
				map_drawable->window,
				map_drawable->style->fg_gc[GTK_WIDGET_STATE (map_drawable)],
				pixmap,
				last_x-29, last_y-29,
				last_x-29 + mouse_dx, last_y-29 + mouse_dy,
				58,58);

		
			//画直线，痕迹
			//删除它
//			if (lat_tmp && lon_tmp)
//				gdk_draw_line(pixmap, gc, last_x, last_y, x, y);
			
			//更新gdk
			gdk_window_process_all_updates();

			
			//在运动过程中，改变中心点的形状
			if(mouse_dx == 0 && mouse_dy == 0)
			{
				//半圆
				gdk_draw_arc (
					map_drawable->window,
					gc_2,
					FALSE,		
					x-15 + mouse_dx,
					y-15 + mouse_dy,
					30,30,		
					0, 360*64);	
				
				
				if(global_wp_on && gpsdata->valid)
				{
					
					bearing = get_bearing(lat, lon, global_wp.lat, global_wp.lon);
					gpsdata->fix.bearing = bearing;

					hand_wp_x =  25 * sinf(bearing);
					hand_wp_y = -25 * cosf(bearing);
					
					//画直线
					gdk_draw_line(map_drawable->window,
							gc_5,
							x + mouse_dx,
							y + mouse_dy,
							x + mouse_dx + hand_wp_x,
							y + mouse_dy + hand_wp_y);

					//画直线
					gdk_draw_line(map_drawable->window,
							gc_4,
							x + mouse_dx,
							y + mouse_dy,
							x + mouse_dx + hand_wp_x,
							y + mouse_dy + hand_wp_y);
					
					osd_wp();
					
				}
				
				
				gdk_draw_line(map_drawable->window,
						gc_5,
						x + mouse_dx,
						y + mouse_dy,
						x + mouse_dx + hand_x,
						y + mouse_dy + hand_y);

				gdk_draw_line(map_drawable->window,
						gc_3,
						x + mouse_dx,
						y + mouse_dy,
						x + mouse_dx + hand_x,
						y + mouse_dy + hand_y);
				//END
			}

			//进入线程，对gtk界面进行操作
			gdk_threads_enter();

			//写文字
			PangoLayout *layout;
			//gchar *s_utf8=node.nodeinfo;
			gchar *s_utf8=Node_3_Name;
			layout = pango_layout_new(gdk_pango_context_get());
			pango_layout_set_text(layout, s_utf8, -1);
			//gdk_draw_layout(drawable, gc, (node.x-20), (node.y+25), layout);
			//gtk_widget_queue_draw_area (map_drawable,x+10, y,50,50);

			gdk_draw_layout(map_drawable->window, gc, x+10, y, layout);


			g_object_unref(layout);



			//更新gdk
			gdk_window_process_all_updates();

			//用完后使用gdk_threads_leave()进行释放
			gdk_threads_leave();



		}
		
		//如果 自动放置到中心点。
		if(global_autocenter)
		{
			if(    (x < (global_drawingarea_width  /2 - global_drawingarea_width  /8) ||
				x > (global_drawingarea_width  /2 + global_drawingarea_width  /8) ||
				y < (global_drawingarea_height /2 - global_drawingarea_height /8) ||
				y > (global_drawingarea_height /2 + global_drawingarea_height /8) ) &&
			
				
				isnan(gpsdata->fix.latitude) ==0 &&
				isnan(gpsdata->fix.longitude)==0 &&
				gpsdata->fix.latitude  !=0 &&
				gpsdata->fix.longitude !=0
				)
			{
				set_mapcenter(gpsdata->fix.latitude, gpsdata->fix.longitude, global_zoom);
			}
		}
		

		

		
		if( gpsdata->valid && lat_tmp!=0 && lon_tmp!=0)
		{
			trip_delta = 6371.0 *  acos(sin(lat) * sin(lat_tmp) + 
				     cos(lat) * cos(lat_tmp) * cos(lon_tmp-lon) );
			
			if(isnan(trip_delta))
			{
				
				trip_delta = 0;
			}
			
			if(trip_delta > TRIP_DELTA_MIN)
			{
				static int cnt = 0;
				
				if(cnt % 2 == 0) {
					tp->time    = gpsdata->fix.time;
					
					tp->lat     = lat;
					tp->lon     = lon;
					tp->lat_deg = gpsdata->fix.latitude;
					tp->lon_deg = gpsdata->fix.longitude;
					tp->alt     = gpsdata->fix.altitude;
					tp->speed   = gpsdata->fix.speed;
					tp->head    = gpsdata->fix.heading;
					tp->hdop    = gpsdata->hdop;
					tp->heart   = 0;
					
					if (trip_delta > SEGMENT_DISTANCE)
						tp->hdop = 999;
	
					
					if (trackpoint_list->length > TRACKPOINT_LIST_MAX_LENGTH)
						g_free(g_queue_pop_head(trackpoint_list));
						
					g_queue_push_tail(trackpoint_list, tp);
				}
			}
		}

		//如果trip旅途 计算器 启用on
		if(trip_counter_on)
		{
			trip_distance += trip_delta;

			
			if(gpsdata->valid && gpsdata->fix.speed > trip_maxspeed)
				trip_maxspeed = gpsdata->fix.speed;
			
			
			
			
			if(trip_time == 0) 
				trip_time_accumulated = 0;
			
			if(trip_counter_got_stopped)
			{
				printf("counter had been stopped \n");
				trip_counter_got_stopped = FALSE;
				trip_time_accumulated = trip_time;
				trip_starttime = 0;
			}
			
			
			if(trip_starttime == 0 && gpsdata->seen_vaild)
			{
				trip_starttime = gpsdata->fix.time;
			}
			
			
			if(trip_starttime > 0 && gpsdata->seen_vaild)
			{
				trip_time = gpsdata->fix.time - trip_starttime + trip_time_accumulated;				
			}
			
			if(trip_time < 0)
			{
				trip_time = 0;
				trip_starttime = 0;
				trip_distance = 0;
				trip_maxspeed = 0;
			}

		}

		else
		{
			printf("trip counter halted\n");
			trip_counter_got_stopped = TRUE;
			lat_tmp = lon_tmp = 0;
		}
		
		
		
		set_label();
		
		
		if(trip_logger_on && gpsdata->valid)
			track_log();
		
		
		if(trip_livelog_on)
			live_log();
		
		if(gpsdata->valid)
		{	
			lat_tmp = lat;
			lon_tmp = lon;
		}




	}	//End of gpsdata
	else
	{
		set_label_nogps();
	}
	
	if(hrm_on && (!hrmdata  || global_reconnect_hrm))
		get_hrm_data();
	else if(hrm_on && hrmdata) {
		osd_hrm(FALSE);
		if(global_infopane_visible)
			set_hrm_labels();
	}
	
	return TRUE; 
}

//重置gpdsd的I/O
gboolean
reset_gpsd_io()
{
	printf("*** %s(): \n",__PRETTY_FUNCTION__);
	
	global_reconnect_gpsd = TRUE;
	g_source_remove(watchdog);

	g_source_remove(sid1); 
	g_source_remove(sid3); 
	
	return FALSE;	
}


//速度
void
osd_speed(gboolean force_redraw)
{
	
	PangoContext		*context = NULL;
	PangoLayout		*layout  = NULL;
	PangoFontDescription	*desc    = NULL;
	
	GdkColor color;
	GdkGC *gc;
	
	gchar *buffer;
	static int x = 10, y = 10;
	static int width = 0, height = 0;

	static double speed_tmp = 0;
	
	double unit_conv = 1;
		
	if(gpsdata && mouse_dx == 0 && mouse_dy == 0) 
	{
		switch (global_speed_unit)
		{
			case 0:
				unit_conv = 1.0;
				break;
			case 1 :
				unit_conv = 1.0/1.609344;
				break;
			case 2 :
				unit_conv = 1.0 / 1.852;
				break;		
		}
		

	
		buffer = g_strdup_printf("%.0f", gpsdata->fix.speed*3.6*unit_conv);
		
		
		context = gtk_widget_get_pango_context (map_drawable);
		layout  = pango_layout_new (context);
		desc    = pango_font_description_new();
		
		pango_font_description_set_absolute_size (desc, 80 * PANGO_SCALE);
		pango_layout_set_font_description (layout, desc);
		pango_layout_set_text (layout, buffer, strlen(buffer));
	
	
		gc = gdk_gc_new (map_drawable->window);
	
		color.red = (gpsdata->fix.speed*3.6*unit_conv > 50) ? 0xffff : 0;
		color.green = 0;
		color.blue = 0;
		
		gdk_gc_set_rgb_fg_color (gc, &color);

		
		
		if(speed_tmp != floor(gpsdata->fix.speed*3.6*unit_conv) || force_redraw)
		{
			
			gdk_draw_drawable (
				map_drawable->window,
				map_drawable->style->fg_gc[GTK_WIDGET_STATE (map_drawable)],
				pixmap,
				0,0,
				0, 0,
				width+10,height+10);
		
			
			if(gpsdata->fix.speed>0.01 && gpsdata->valid) 
				gdk_draw_layout(map_drawable->window,
						gc,
						x, y,
						layout);
			
			
			pango_layout_get_pixel_size(layout, &width, &height);
		}
		
		speed_tmp = floor(gpsdata->fix.speed*3.6*unit_conv);
		
		g_free(buffer);
		pango_font_description_free (desc);
		g_object_unref (layout);
		g_object_unref (gc);
	}
}

//no GPSD found,没有发现GPSD
void
set_label_nogps()
{
	static GtkLabel *label=NULL;
	static gchar buffer[BUFSIZE];
	int num_dl_threads = 0;

	if(label == NULL)
		label   = GTK_LABEL(lookup_widget(window_main, "label4"));
	
	num_dl_threads = update_thread_number(0);
	if(num_dl_threads && !global_tiles_in_dl_queue)
	{	
		g_snprintf(buffer, BUFSIZE,
			"<b>no GPSD found</b> - <span foreground='#0000ff'><b>D%d</b></span>",
			num_dl_threads);
	}
	else if (num_dl_threads && global_tiles_in_dl_queue)
		g_snprintf(buffer, BUFSIZE,
			"<b>no GPSD found</b> - <span foreground='#0000ff'><b>D%d</b></span> - <b>[%d]</b>",
			num_dl_threads, global_tiles_in_dl_queue);
	else
		g_snprintf(buffer, BUFSIZE, "<b>no GPSD found</b>");
	
	if(global_new_msg)
		g_snprintf(buffer, BUFSIZE, "<span foreground='#ff0000'><b>New Message arrived. Click here.</b></span>");
	
	gtk_label_set_label(label, buffer);

}

//设置标签，显示经纬度和速度
void
set_label()
{
	static GtkLabel *label=NULL,   *label31, *label38, *label39;
	static GtkLabel *label41, *label42, *label43, *label45;
	static GtkLabel *label66, *label68, *label70;
	static gchar buffer[BUFSIZE];
	static gchar numdl_buf[64], dl_buf[64], ff_buf[64], tr_buf[64];
	static gchar speedunit[5], distunit[3], altunit[3];
	int trip_hours, trip_minutes, trip_seconds;
	int num_dl_threads = 0;
	time_t time_sec;
	struct tm  *ts;
	double unit_conv = 1, unit_conv_alt = 1;
	
	osd_speed(FALSE);
	
	if(global_speed_unit==1)
	{
		unit_conv = 1.0/1.609344;
		g_sprintf(speedunit, "%s","mph");
		g_sprintf(distunit, "%s", "m");
	}
	else if(global_speed_unit==2)
	{
		unit_conv = 1.0/1.852;
		g_sprintf(speedunit, "%s","kn");
		g_sprintf(distunit, "%s", "NM");
	}
	else
	{
		g_sprintf(speedunit, "%s","km/h");
		g_sprintf(distunit, "%s", "km");
	}
	
	
	if(global_alt_unit==1)
	{
		unit_conv_alt = 1.0/0.3048;
		g_sprintf(altunit, "%s", "ft");
	}
	else
		g_sprintf(altunit, "%s", "m");
	
	if(global_auto_download)
		g_sprintf(dl_buf, "%s", "");
	else
		g_sprintf(dl_buf, "%s", "<span foreground='#ff0000'><b>!</b></span>");
	
	if (global_fftimer_running)
		g_sprintf(ff_buf, "%s", "<span foreground='#00e000'><b>f</b></span>");
	else
		g_sprintf(ff_buf, "%s", "");
	
	if (trip_logger_on)
		g_sprintf(tr_buf, "%s", "<span foreground='#00e000'><b>t</b></span>");
	else
		g_sprintf(tr_buf, "%s", "");
	
	if(label == NULL)
	{
		label   = GTK_LABEL(lookup_widget(window_main, "label4"));
		label45 = GTK_LABEL(lookup_widget(window_main, "label45"));
		label41 = GTK_LABEL(lookup_widget(window_main, "label41"));
		label31 = GTK_LABEL(lookup_widget(window_main, "label31"));
		label38 = GTK_LABEL(lookup_widget(window_main, "label38"));
		label39 = GTK_LABEL(lookup_widget(window_main, "label39"));
		label42 = GTK_LABEL(lookup_widget(window_main, "label42"));
		label43 = GTK_LABEL(lookup_widget(window_main, "label43"));
		label66 = GTK_LABEL(lookup_widget(window_main, "label66"));
		label68 = GTK_LABEL(lookup_widget(window_main, "label68"));
		label70 = GTK_LABEL(lookup_widget(window_main, "label70"));
	}


	
	
	
	num_dl_threads = update_thread_number(0);
	
	if(num_dl_threads && !global_tiles_in_dl_queue)
		g_sprintf(numdl_buf, "<span foreground='#0000ff'><b>D%d</b></span> ", 
			  num_dl_threads);
	else if (num_dl_threads && global_tiles_in_dl_queue)
		g_sprintf(numdl_buf, "<span foreground='#0000ff'><b>D%d</b></span>-%d ", 
			  num_dl_threads, global_tiles_in_dl_queue);
	else
		g_sprintf(numdl_buf, "%s", "");
	

	g_snprintf(buffer, BUFSIZE,
		"%s%s%s%s<b>%4.1f</b>%s "
		"<small>trp </small><b>%.2f</b>%s "
		"<small>alt </small><b>%.0f</b>%s "
		"<small>hdg </small><b>%.0f</b>° "
		"<small></small>%d/%.1f",
		numdl_buf,
		dl_buf,
		tr_buf,
		ff_buf,
		gpsdata->fix.speed * 3.6 * unit_conv,	speedunit,
		trip_distance * unit_conv,		distunit,
		gpsdata->fix.altitude * unit_conv_alt,	altunit,
		gpsdata->fix.heading * unit_conv,
		gpsdata->satellites_used,
		gpsdata->hdop);

	if(global_new_msg)
		g_snprintf(buffer, BUFSIZE, "<span foreground='#ff0000'><b>New Message arrived. Click here.</b></span>");

	gtk_label_set_label(label, buffer);


	if(global_infopane_visible)
	{
		
		
		
		
		
		time_sec = (time_t)gpsdata->fix.time;
		ts = localtime(&time_sec);
		
		
		strftime(buffer, sizeof(buffer), "<big><b>%a %Y-%m-%d %H:%M:%S</b></big>", ts); 
		gtk_label_set_label(label41,buffer);
	
		
		switch (global_latlon_unit)
		{
			case 0:
				g_snprintf(buffer, BUFSIZE, "<big><b>%f - %f</b></big>", gpsdata->fix.latitude, gpsdata->fix.longitude);
				break;
			case 1:
				g_snprintf(buffer, BUFSIZE, "<big><b>%s   %s</b></big>", 
					  latdeg2latmin(gpsdata->fix.latitude),
					  londeg2lonmin(gpsdata->fix.longitude));
				break;
			case 2:
				g_snprintf(buffer, BUFSIZE, "<big><b>%s   %s</b></big>", 
					  latdeg2latsec(gpsdata->fix.latitude),
					  londeg2lonsec(gpsdata->fix.longitude));
		}
		gtk_label_set_label(label31,buffer);
		
		
		g_snprintf(buffer, BUFSIZE, 
			"<b><span foreground='#0000ff'><span font_desc='45'>%.1f</span></span></b> %s", 
			gpsdata->fix.speed*3.6*unit_conv, speedunit);
		gtk_label_set_label(label38,buffer);
	
		
		g_snprintf(buffer, BUFSIZE, "<big><b>%.1f %s</b></big>", gpsdata->fix.altitude * unit_conv_alt, altunit);
		gtk_label_set_label(label39,buffer);
		
		
		g_snprintf(buffer, BUFSIZE, "<big><b>%.1f°</b></big> ", gpsdata->fix.heading);
		gtk_label_set_label(label42,buffer);
		
		
		g_snprintf(buffer, BUFSIZE, "<big><b>%d</b>  <small>HDOP</small><b> %.1f</b></big>", 
				gpsdata->satellites_used, gpsdata->hdop);
		gtk_label_set_label(label43,buffer);
	
		
		
		
	
		
		g_snprintf(buffer, BUFSIZE, "<big><b>%.3f</b></big> <small>%s</small>", trip_distance*unit_conv,distunit);
		gtk_label_set_label(label45,buffer);
	
	
		
		trip_hours   = trip_time / 3600;
		trip_minutes = ((int)trip_time%3600)/60;
		trip_seconds = (int)trip_time % 60;
		
		if (trip_seconds < 10 && trip_minutes < 10)
		{
			g_sprintf(buffer, "<big><b>%d:0%d:0%d</b></big>",trip_hours,trip_minutes,trip_seconds);
		}
		else if (trip_seconds < 10)
			g_sprintf(buffer, "<big><b>%d:%d:0%d</b></big>",trip_hours,trip_minutes,trip_seconds);
		else if (trip_minutes < 10)
			g_sprintf(buffer, "<big><b>%d:0%d:%d</b></big>",trip_hours,trip_minutes,trip_seconds);
		else
			g_sprintf(buffer, "<big><b>%d:%d:%d</b></big>",trip_hours,trip_minutes,trip_seconds);
	
		gtk_label_set_label(label66,buffer);
	
		
		g_sprintf(buffer, "<big><b>%.1f</b></big><small> %s</small>", trip_distance*3600*unit_conv/(trip_time+2.0), speedunit);
		gtk_label_set_label(label68,buffer);
	
		
		g_sprintf(buffer, "<big><b>%.1f</b></big><small> %s</small>", trip_maxspeed*3.6*unit_conv, speedunit);
		gtk_label_set_label(label70,buffer);
	}
}



//解析GPS nmea
void
parse_nmea_rmc(char *nmea)
{
	gchar **array;
	gchar lat_dec[3], lon_dec[4];
	double	lat_min, lat=0, lon_min,lon=0;
	gchar hour[3],min[3],sec[3],year[3],month[3],day[3];
	int i=0;

	typedef struct tm tm_t;	
	static tm_t *tm = NULL;

	if(!tm) tm = g_new0(tm_t,1);
		
	array = g_strsplit(nmea,",",0);

	while (array[i]) i++;

	g_source_remove(watchdog);
	watchdog = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT_IDLE,60,reset_gpsd_io,NULL,NULL);
	
	if(i>=9)
	{
		
		if (strlen(array[1]) >= 6)
		{
			strncpy(hour, array[1],2);
			hour[2]='\0';
			strncpy(min, array[1]+2,2);
			min[2]='\0';
			strncpy(sec, array[1]+4,2);
			sec[2]='\0';
		}
		
		
		if (strlen(array[9]) == 6)
		{
			strncpy(day, array[9],2);
			day[2]='\0';
			strncpy(month, array[9]+2,2);
			month[2]='\0';
			strncpy(year, array[9]+4,2);
			year[2]='\0';

			tm->tm_sec = atoi(sec);
			tm->tm_min = atoi(min);
			tm->tm_hour= atoi(hour);
			tm->tm_mday= atoi(day);
			tm->tm_mon = atoi(month)-1;
			tm->tm_year= atoi(year)+100;
	
			
			gpsdata->fix.time = (double) mktime(tm);
			
			
		}
		
		
		if (strlen(array[3]) >= 3)
		{
			strncpy(lat_dec, array[3], 2);
			lat_dec[2]='\0';
			lat_min = atof(array[3]+2);
			lat = atof(lat_dec) + (lat_min/60);
			if (strcmp(array[4],"S")==0)
			{
				lat = -lat;
			}
		}
		
		
		if (strlen(array[5]) >= 4)
		{
			strncpy(lon_dec, array[5], 3);
			lon_dec[3]='\0';
			lon_min = atof(array[5]+3);
			lon = atof(lon_dec) + (lon_min/60);
			if (strcmp(array[6],"W")==0)
			{
				lon = -lon;
			}
		}
		
		gpsdata->valid = (strcmp(array[2],"A")==0) ? TRUE : FALSE;
		
		if(gpsdata->valid)
		{
			gpsdata->seen_vaild = TRUE;
			gpsdata->fix.latitude = lat;
			gpsdata->fix.longitude = lon;
			gpsdata->fix.speed = atof(array[7])*0.514444; 
			gpsdata->fix.heading = atof(array[8]);
		}
	}
	else
		printf("%s(): YIKES. not enough fields. GPS receiver broken?\n",__PRETTY_FUNCTION__);
	
	g_strfreev(array);
}



void
parse_nmea_gga(char *nmea)
{		
	gchar **array;
	int i=0;

	array = g_strsplit(nmea,",",0);
	
	while (array[i]) i++;

	if(i>=9)
	{
		gpsdata->satellites_used = atoi(array[7]);
		
		if(atoi(array[6])>0)  
		{
			gpsdata->hdop = atof(array[8]);
			gpsdata->fix.altitude = atof(array[9]);
		}
	}
	g_strfreev(array);
}

void
parse_nmea_gsv(char *nmea)
{		
	gchar **array;
	int i=0;
		
	array = g_strsplit(nmea,",",0);
	while (array[i]) i++;
			
	if (i>=3)
		gpsdata->satellites_inview = atoi(array[3]);

	g_strfreev(array);
}


static gboolean
cb_gpsd_io_error(GIOChannel *src, GIOCondition condition, gpointer data)
{
	printf("*** %s(): \n",__PRETTY_FUNCTION__);
	g_free(gpsdata);
	gpsdata = NULL;
	g_source_remove(sid1); 
	g_source_remove(sid3); 
	
	
	return FALSE; 
}



static gboolean
cb_gpsd_data(GIOChannel *src, GIOCondition condition, gpointer data)
{

	gsize length;
	GError *error = NULL;
	gchar *str_return;
	GIOStatus status;

	

	status =  g_io_channel_read_line(
				gpsd_io_channel,
				&str_return,
				&length,
				NULL,
				&error);

	if(status == G_IO_STATUS_NORMAL)
	{		
		if(strncmp(str_return,"$GPGGA",6)==0)
		{
			parse_nmea_gga(str_return);
		}
		else if (strncmp(str_return,"$GPRMC",6)==0)
		{
			parse_nmea_rmc(str_return);
		}	
	}
	else
	{
		if (error)
			printf("%s \n", error->message);
		
		
	}
	
	g_free(str_return);

	return TRUE;
}


//获取GPS信息
void 
get_gps()
{
	g_thread_create(&get_gps_thread, NULL, FALSE, NULL);
}


//获取GPS信息的线程
void *
get_gps_thread(void *ptr)
{
	
	static int sock = 0;
	int conn, len;
	char buffer[501]; 
	struct sockaddr_in server;
	char buffer_send[] = "r";
	char buffer_send2[] = "?WATCH={\"raw\":0,\"nmea\":true}";

			
	if (sock) sock = close(sock);
		
	
	server.sin_family	= AF_INET;
	server.sin_addr.s_addr	= inet_addr(global_server);
	server.sin_port		= htons (atoi(global_port));
	memset(&(server.sin_zero), '\0', 8);		
	
	
	sock = socket(AF_INET, SOCK_STREAM, 0);
	conn = connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr));

	if(conn == 0)
	{
		fprintf(stderr, "connection to gpsd SUCCEEDED \n");

		global_reconnect_gpsd = FALSE;
		
		if(!gpsdata)
		{
			gpsdata = g_new0(gps_data_t,1);
		}

		len = write(sock, buffer_send2, strlen(buffer_send2));
		len = recv(sock, buffer, 500, 0);
		
		buffer[len]='\0'; 
		
		if(!g_strrstr_len(buffer,20,"class"))
			len = write(sock, buffer_send, strlen(buffer_send));
		
	
		//看门狗
		watchdog = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT_IDLE,60,reset_gpsd_io,NULL,NULL);
		
		//GPSD  IO 频道
		gpsd_io_channel = g_io_channel_unix_new(sock);
		//设置标记flags
		g_io_channel_set_flags(gpsd_io_channel, G_IO_FLAG_NONBLOCK, NULL);
		
		
		sid1 = g_io_add_watch_full(gpsd_io_channel, G_PRIORITY_HIGH_IDLE+200, G_IO_ERR | G_IO_HUP, cb_gpsd_io_error, NULL, NULL);
		
		
		sid3 = g_io_add_watch_full(gpsd_io_channel, G_PRIORITY_HIGH_IDLE+200, G_IO_IN | G_IO_PRI, cb_gpsd_data, NULL, NULL);
	
	}
	
	return NULL;
}


//地图尺寸指示器
void
map_scale_indicator()
{
	int y, width, height, max_bar_length=250;
	float distance, factor, lat, lon1, lon2;
	char *buffer=NULL;
	GdkColor color;
	static GdkGC *gc=NULL, *gc1=NULL;
	
	PangoContext		*context = NULL;
	PangoLayout		*layout  = NULL;
	PangoFontDescription	*desc    = NULL;
	
	y = map_drawable->allocation.height - 8;
	
	if(gc == NULL)
	{
		gc   = gdk_gc_new(pixmap);
		gc1  = gdk_gc_new(pixmap);
	}
	color.red   = 0;
	color.green = 0;
	color.blue  = 0;
	
	gdk_gc_set_rgb_fg_color(gc, &color);
        gdk_gc_set_line_attributes(gc,
                        5, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_ROUND);

	color.red   = 65000;
	color.green = 65000;
	color.blue  = 65000;
	
	gdk_gc_set_rgb_fg_color(gc1, &color);
        gdk_gc_set_line_attributes(gc1,
                        3, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_ROUND);
	


	lat   = pixel2lat(global_zoom, global_y+y);
	lon1  = pixel2lon(global_zoom, 0);
	lon2  = pixel2lon(global_zoom, max_bar_length);

	distance = get_distance(lat, lon1, lat, lon2);
	
	buffer = distance2scale(distance, &factor);
	max_bar_length *= factor;
	
	gdk_draw_line(map_drawable->window, gc, 4, y, max_bar_length+6, y);
	gdk_draw_line(map_drawable->window, gc1,5, y, max_bar_length+5, y);	

	
	context = gtk_widget_get_pango_context (map_drawable);
	layout  = pango_layout_new (context);
	desc    = pango_font_description_new();
	
	pango_font_description_set_absolute_size (desc, 12 * PANGO_SCALE);
	pango_layout_set_font_description (layout, desc);
	pango_layout_set_text (layout, buffer, strlen(buffer));


	
	pango_layout_get_pixel_size(layout, &width, &height);

	
	
	gdk_gc_set_line_attributes(gc,
                        height+2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_ROUND);	

        gdk_gc_set_line_attributes(gc1,
                        height, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_ROUND);	

	gdk_draw_line(map_drawable->window, gc1, 22, y-height/2+6, 20+width+6, y-height/2+6);

     

		gdk_draw_layout(map_drawable->window,
				gc,
				25, y-height+7,
				layout);
	


	g_free(buffer);
	pango_font_description_free (desc);
	g_object_unref (layout);
	
	
	
}


//距离转化为尺寸,
char *
distance2scale(float distance, float *factor)
{
	float unit_conv=1;
	char *buf = NULL;
	char unit[5];
	
	switch (global_speed_unit)
	{
		case METRICAL:
			unit_conv = 1.0;
			strncpy(unit, "km", 3);
			break;
		case IMPERIAL :
			unit_conv = 1.0/1.609344;
			strncpy(unit, "m", 2);
			break;
		case NAUTICAL :
			unit_conv = 1.0 / 1.852;
			strncpy(unit, "NM", 3);
			break;		
	}
	
	distance *= unit_conv;
	if (distance >= 5000) {
		buf = g_strconcat("5000", unit, NULL);
		*factor = 5000/distance;
	}
	else if (distance < 5000 && distance >= 2000) {
		buf = g_strconcat("2000", unit, NULL);
		*factor = 2000/distance;
	}
	else if (distance < 2000 && distance >= 1000) {
		buf = g_strconcat("1000", unit, NULL);
		*factor = 1000/distance;
	}
	else if (distance < 1000 && distance >= 500) {
		buf = g_strconcat("500", unit, NULL);
		*factor = 500/distance;
	}
	else if (distance < 500 && distance >= 200) {
		buf = g_strconcat("200", unit, NULL);
		*factor = 200/distance;
	}
	else if (distance < 200 && distance >= 100) {
		buf = g_strconcat("100", unit, NULL);
		*factor = 100/distance;
	}
	else if (distance < 100 && distance >= 50) {
		buf = g_strconcat("50", unit, NULL);
		*factor = 50/distance;
	}
	else if (distance < 50 && distance >= 20) {
		buf = g_strconcat("20", unit, NULL);
		*factor = 20/distance;
	}
	else if (distance < 20 && distance >= 10) {
		buf = g_strconcat("10", unit, NULL);
		*factor = 10/distance;
	}
	else if (distance < 10 && distance >= 5) {
		buf = g_strconcat("5", unit, NULL);
		*factor = 5/distance;
	}
	else if (distance < 5 && distance >= 2) {
		buf = g_strconcat("2", unit, NULL);
		*factor = 2/distance;
	}
	else if (distance < 2 && distance >= 1) {
		buf = g_strconcat("1", unit, NULL);
		*factor = 1/distance;
	}
	else if(global_speed_unit == METRICAL)
	{
		if (distance < 1 && distance >= 0.5) {
			buf = g_strdup("500m");
			*factor = 0.5/distance;
		}
		else if (distance < 0.5 && distance >= 0.2) {
			buf = g_strdup("200m");
			*factor = 0.2/distance;
		}
		else if (distance < 0.2 && distance >= 0.1) {
			buf = g_strdup("100m");
			*factor = 0.1/distance;
		}
		else if (distance < 0.1 && distance >= 0.05) {
			buf = g_strdup("50m");
			*factor = 0.05/distance;
		}
		else if (distance < 0.05 && distance >= 0.02) {
			buf = g_strdup("20m");
			*factor = 0.02/distance;
		}
		else {
			buf = g_strdup("10m");
			*factor = 0.01/distance;
		}
	}
	else if(global_speed_unit == IMPERIAL)
	{
		distance *= 5280;
		if (distance >= 5000) {
			buf = g_strdup("5000ft");
			*factor = 5000/distance;
		}
		else if (distance < 5000 && distance >= 2000) {
			buf = g_strdup("2000ft");
			*factor = 2000/distance;
		}
		else if (distance < 2000 && distance >= 1000) {
			buf = g_strdup("1000ft");
			*factor = 1000/distance;
		}
		else if (distance < 1000 && distance >= 500) {
			buf = g_strdup("500ft");
			*factor = 500/distance;
		}
		else if (distance < 500 && distance >= 200) {
			buf = g_strdup("200ft");
			*factor = 200/distance;
		}
		else {
			buf = g_strdup("100ft");
			*factor = 100/distance;
		}
	}
	else if(global_speed_unit == NAUTICAL)
	{
		if (distance < 1 && distance >= 0.5) {
			buf = g_strdup("0.5NM");
			*factor = 0.5/distance;
		}
		else if (distance < 0.5 && distance >= 0.2) {
			buf = g_strdup("0.2NM");
			*factor = 0.2/distance;
		}
		else if (distance < 0.2 && distance >= 0.1) {
			buf = g_strdup("0.1NM");
			*factor = 0.1/distance;
		}
		else if (distance < 0.1 && distance >= 0.05) {
			buf = g_strdup("0.05NM");
			*factor = 0.05/distance;
		}
		else if (distance < 0.05 && distance >= 0.02) {
			buf = g_strdup("0.02NM");
			*factor = 0.02/distance;
		}
		else {
			buf = g_strdup("0.01NM");
			*factor = 0.01/distance;
		}
	}

	if(!buf)
		buf=g_strdup("bingo");

	return buf;
}
